home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2001 May / SGI Freeware 2001 May - Disc 1.iso / dist / fw_mysql.idb / usr / freeware / share / sql-bench / test-insert.z / test-insert
Encoding:
Text File  |  1999-10-18  |  30.1 KB  |  1,106 lines

  1. #!/usr/bin/perl
  2. #
  3. # Test of creating a simple table and inserting $record_count records in it,
  4. # $opt_loop_count rows in order, $opt_loop_count rows in reverse order and
  5. # $opt_loop_count rows in random order
  6. #
  7. # changes made for Oracle compatibility
  8. # - $limits{'func_odbc_mod'} is OK from crash-me, but it fails here so set we
  9. #   set it to 0 in server-cfg
  10. # - the default server config runs out of rollback segments, so I added a couple
  11. #   of disconnect/connects to reset
  12. ##################### Standard benchmark inits ##############################
  13.  
  14. use DBI;
  15. use Benchmark;
  16.  
  17. $opt_loop_count=100000;        # number of rows/3
  18. $small_loop_count=10;        # Loop for full table retrieval
  19. $range_loop_count=$small_loop_count*50;
  20. $many_keys_loop_count=$opt_loop_count;
  21.  
  22. chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
  23. require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
  24.  
  25. if ($opt_loop_count < 256)
  26. {
  27.   $opt_loop_count=256;        # Some tests must have some data to work!
  28. }
  29.  
  30. if ($opt_small_test)
  31. {
  32.   $opt_loop_count/=100;
  33.   $range_loop_count/=10;
  34.   $many_keys_loop_count=$opt_loop_count/10;
  35. }
  36. elsif ($opt_small_tables)
  37. {
  38.   $opt_loop_count=10000;        # number of rows/3
  39.   $many_keys_loop_count=$opt_loop_count;
  40. }
  41. elsif ($opt_small_key_tables)
  42. {
  43.   $many_keys_loop_count/=10;
  44. }
  45.  
  46. print "Testing the speed of inserting data into 1 table and do some selects on it.\n";
  47. print "The tests are done with a table that has $opt_loop_count rows.\n\n";
  48.  
  49. ####
  50. #### Generating random keys
  51. ####
  52.  
  53. print "Generating random keys\n";
  54. $random[$opt_loop_count]=0;
  55. for ($i=0 ; $i < $opt_loop_count ; $i++)
  56. {
  57.   $random[$i]=$i+$opt_loop_count;
  58. }
  59.  
  60. my $tmpvar=1;
  61. for ($i=0 ; $i < $opt_loop_count ; $i++)
  62. {
  63.   $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  64.   $swap=$tmpvar % $opt_loop_count;
  65.   $tmp=$random[$i]; $random[$i]=$random[$swap]; $random[$swap]=$tmp;
  66. }
  67.  
  68. $total_rows=$opt_loop_count*3;
  69.  
  70. ####
  71. ####  Connect and start timeing
  72. ####
  73. $start_time=new Benchmark;
  74. $dbh = $server->connect();
  75. ####
  76. #### Create needed tables
  77. ####
  78.  
  79. goto keys_test if ($opt_stage == 2);
  80. goto select_test if ($opt_skip_create);
  81.  
  82. print "Creating tables\n";
  83. $dbh->do("drop table bench1");
  84. do_many($dbh,$server->create("bench1",
  85.                  ["id int NOT NULL",
  86.                   "id2 int NOT NULL",
  87.                   "id3 int NOT NULL",
  88.                   "dummy1 char(30)"],
  89.                  ["primary key (id,id2)",
  90.                  "index index_id3 (id3)"]));
  91.  
  92. if ($opt_lock_tables)
  93. {
  94.   $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  95. }
  96.  
  97. if ($opt_fast && $opt_server eq "pg")
  98. {
  99.   $server->vacuum($dbh);
  100. }
  101.  
  102. ####
  103. #### Insert $total_rows records in order, in reverse order and random.
  104. ####
  105.  
  106. $loop_time=new Benchmark;
  107.  
  108. if ($opt_fast_insert)
  109. {
  110.   $query="insert into bench1 values ";
  111. }
  112. else
  113. {
  114.   $query="insert into bench1 (id,id2,id3,dummy1) values ";
  115. }
  116.  
  117. if (($opt_fast || $opt_fast_insert) && $limits->{'multi_value_insert'})
  118. {
  119.   $query_size=$server->{'limits'}->{'query_size'};
  120.  
  121.   print "Inserting $opt_loop_count multiple-value rows in order\n";
  122.   $res=$query;
  123.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  124.   {
  125.     $tmp= "($i,$i,$i,'ABCDEFGHIJ'),";
  126.     if (length($tmp)+length($res) < $query_size)
  127.     {
  128.       $res.= $tmp;
  129.     }
  130.     else
  131.     {
  132.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  133.       $res=$query . $tmp;
  134.     }
  135.   }
  136.   print "Inserting $opt_loop_count multiple-value rows in reverse order\n";
  137.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  138.   {
  139.     $tmp= "(" . ($total_rows-1-$i) . "," .($total_rows-1-$i) .
  140.       "," .($total_rows-1-$i) . ",'BCDEFGHIJK'),";
  141.     if (length($tmp)+length($res) < $query_size)
  142.     {
  143.       $res.= $tmp;
  144.     }
  145.     else
  146.     {
  147.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  148.       $res=$query . $tmp;
  149.     }
  150.   }
  151.   print "Inserting $opt_loop_count multiple-value rows in random order\n";
  152.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  153.   {
  154.     $tmp= "(" . $random[$i] . "," . $random[$i] . "," . $random[$i] .
  155.       ",'CDEFGHIJKL')," or die $DBI::errstr;
  156.     if (length($tmp)+length($res) < $query_size)
  157.     {
  158.       $res.= $tmp;
  159.     }
  160.     else
  161.     {
  162.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  163.       $res=$query . $tmp;
  164.     }
  165.   }
  166.   $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  167. }
  168. else
  169. {
  170.   print "Inserting $opt_loop_count rows in order\n";
  171.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  172.   {
  173.     $sth = $dbh->do($query . "($i,$i,$i,'ABCDEFGHIJ')") or die $DBI::errstr;
  174.   }
  175.  
  176.   print "Inserting $opt_loop_count rows in reverse order\n";
  177.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  178.   {
  179.     $sth = $dbh->do($query . "(" . ($total_rows-1-$i) . "," .
  180.             ($total_rows-1-$i) . "," .
  181.             ($total_rows-1-$i) . ",'BCDEFGHIJK')")
  182.       or die $DBI::errstr;
  183.   }
  184.  
  185.   print "Inserting $opt_loop_count rows in random order\n";
  186.  
  187.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  188.   {
  189.     $sth = $dbh->do($query . "(". $random[$i] . "," . $random[$i] .
  190.             "," . $random[$i] . ",'CDEFGHIJKL')") or die $DBI::errstr;
  191.   }
  192. }
  193.  
  194. $end_time=new Benchmark;
  195. print "Time for insert (" . ($total_rows) . "): " .
  196.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  197.  
  198. if ($opt_fast && $opt_server eq "pg")
  199. {
  200.   $server->vacuum($dbh);
  201. }
  202.  
  203. ####
  204. #### insert $opt_loop_count records with duplicate id
  205. ####
  206.  
  207. print "Testing insert of duplicates\n";
  208. $loop_time=new Benchmark;
  209. for ($i=0 ; $i < $opt_loop_count ; $i++)
  210. {
  211.   $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  212.   $tmp=$tmpvar % ($total_rows);
  213.   $tmpquery = "$query" . "$tmp" . ",1,2,'D')";
  214.   if ($dbh->do($tmpquery))
  215.   {
  216.     die "Didn't get an error when inserting duplicate record $tmp\n";
  217.   }
  218. }
  219.  
  220. $end_time=new Benchmark;
  221. print "Time for insert_duplicates (" . ($total_rows) . "): " .
  222.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  223.  
  224. if ($opt_fast && $opt_server eq "pg")
  225. {
  226.   $server->vacuum($dbh);
  227. }
  228.  
  229. ####
  230. #### Do some selects on the table
  231. ####
  232.  
  233. select_test:
  234.  
  235. print "Retrieving data from the table\n";
  236. $loop_time=new Benchmark;
  237. $error=0;
  238.  
  239. # It's really a small table, so we can try a select on everything
  240.  
  241. $count=0;
  242. for ($i=1 ; $i <= $small_loop_count ; $i++)
  243. {
  244.   if (($found_rows=fetch_all_rows($dbh,"select id from bench1")) !=
  245.       $total_rows)
  246.   {
  247.     if (!$error++)
  248.     {
  249.       print "Warning: Got $found_rows rows when selecting a hole table of " . ($total_rows) . " rows\nContact the database or DBD author!\n";
  250.     }
  251.   }
  252.   $count+=$found_rows;
  253. }
  254.  
  255. $end_time=new Benchmark;
  256. print "Time for select_big ($small_loop_count:$count): " .
  257.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  258.  
  259. $loop_time=new Benchmark;
  260. $estimated=0;
  261. $rows=0;
  262. $count=0;
  263. for ($i=1 ; $i <= $small_loop_count/2 ; $i++)
  264. {
  265.   $rows+=fetch_all_rows($dbh,"select id from bench1 order by id",1);
  266.   $rows+=fetch_all_rows($dbh,"select id from bench1 order by id desc",1);
  267.   $count+=2;
  268.   $end_time=new Benchmark;
  269.   last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
  270.                      $small_loop_count));
  271. }
  272. if ($estimated)
  273. { print "Estimated time"; }
  274. else
  275. { print "Time"; }
  276. print " for order_by_key ($count:$rows): " .
  277.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  278.  
  279.  
  280. $loop_time=new Benchmark;
  281. $estimated=0;
  282. $rows=0;
  283. $count=0;
  284. for ($i=1 ; $i <= $small_loop_count/2 ; $i++)
  285. {
  286.   $rows+=fetch_all_rows($dbh,"select id2 from bench1 order by id2",1);
  287.   $rows+=fetch_all_rows($dbh,"select id2 from bench1 order by id2 desc",1);
  288.   $count+=2;
  289.   $end_time=new Benchmark;
  290.   last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
  291.                      $small_loop_count));
  292. }
  293. if ($estimated)
  294. { print "Estimated time"; }
  295. else
  296. { print "Time"; }
  297. print " for order_by ($count:$rows): " .
  298.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  299.  
  300.  
  301. # Test select that is very popular when using ODBC
  302.  
  303. check_or_range("id","select_range_prefix");
  304. check_or_range("id3","select_range");
  305.  
  306. # Check reading on direct key on id and id3
  307.  
  308. check_select_key("id","select_key_prefix");
  309. check_select_key("id3","select_key");
  310.  
  311. ####
  312. #### A lot of simple selects on ranges
  313. ####
  314.  
  315. @Q=("select * from bench1 where !id!=3 or !id!=2 or !id!=1 or !id!=4 or !id!=16 or !id!=10",
  316.     6,
  317.     "select * from bench1 where !id!>=" . ($total_rows-1) ." or !id!<1",
  318.     2,
  319.     "select * from bench1 where !id!>=1 and !id!<=2",
  320.     2,
  321.     "select * from bench1 where (!id!>=1 and !id!<=2) or (!id!>=1 and !id!<=2)",
  322.     2,
  323.     "select * from bench1 where !id!>=1 and !id!<=10 and !id!<=5",
  324.     5,
  325.     "select * from bench1 where (!id!>0 and !id!<2) or !id!>=" . ($total_rows-1),
  326.     2,
  327.     "select * from bench1 where (!id!>0 and !id!<2) or (!id!>= " . ($opt_loop_count/2) . " and !id! <= " . ($opt_loop_count/2+2) . ") or !id! = " . ($opt_loop_count/2-1),
  328.     5,
  329.     "select * from bench1 where (!id!>=5 and !id!<=10) or (!id!>=1 and !id!<=4)",
  330.     10,
  331.     "select * from bench1 where (!id!=1 or !id!=2) and (!id!=3 or !id!=4)",
  332.     0,
  333.     "select * from bench1 where (!id!=1 or !id!=2) and (!id!=2 or !id!=3)",
  334.     1,
  335.     "select * from bench1 where (!id!=1 or !id!=5 or !id!=20 or !id!=40) and (!id!=1 or !id!>=20 or !id!=4)",
  336.     3,
  337.     "select * from bench1 where ((!id!=1 or !id!=3) or (!id!>1 and !id!<3)) and !id!<=2",
  338.     2,
  339.     "select * from bench1 where (!id! >= 0 and !id! < 4) or (!id! >=4 and !id! < 6)",
  340.     6,
  341.     "select * from bench1 where !id! <= -1 or (!id! >= 0 and !id! <= 5) or (!id! >=4 and !id! < 6) or (!id! >=6 and !id! <=7) or (!id!>7 and !id! <= 8)",
  342.     9,
  343.     "select * from bench1 where (!id!>=1 and !id!<=2 or !id!>=4 and !id!<=5) or (!id!>=0 and !id! <=10)",
  344.     11,
  345.     "select * from bench1 where (!id!>=1 and !id!<=2 or !id!>=4 and !id!<=5) or (!id!>2 and !id! <=10)",
  346.     10,
  347.     "select * from bench1 where (!id!>1 or !id! <1) and !id!<=2",
  348.     2,
  349.     "select * from bench1 where !id! <= 2 and (!id!>1 or !id! <=1)",
  350.     3,
  351.     "select * from bench1 where (!id!>=1 or !id! <1) and !id!<=2",
  352.     3,
  353.     "select * from bench1 where (!id!>=1 or !id! <=2) and !id!<=2",
  354.     3
  355.     );
  356.  
  357. print "\nTest of compares with simple ranges\n";
  358. check_select_range("id","select_range_prefix");
  359. check_select_range("id3","select_range");
  360.  
  361. ####
  362. #### Some group queries
  363. ####
  364.  
  365. if ($limits->{'group_functions'})
  366. {
  367.   $loop_time=new Benchmark;
  368.   $count=1;
  369.  
  370.   for ($tests=0 ; $tests < $small_loop_count ; $tests++)
  371.   {
  372.     $sth=$dbh->prepare($query="select count(*) from bench1") or die $DBI::errstr;
  373.     $sth->execute or die $sth->errstr;
  374.     if (($sth->fetchrow_array)[0] != $total_rows)
  375.     {
  376.       print "Warning: '$query' returned wrong result\n";
  377.     }
  378.     $sth->finish;
  379.  
  380.     # min, max in keys are very normal
  381.     $count+=7;
  382.     fetch_all_rows($dbh,"select min(id) from bench1");
  383.     fetch_all_rows($dbh,"select max(id) from bench1");
  384.     fetch_all_rows($dbh,"select sum(id+0.0) from bench1");
  385.     fetch_all_rows($dbh,"select min(id3),max(id3),sum(id3 +0.0) from bench1");
  386.     if ($limits->{'group_func_sql_min_str'})
  387.     {
  388.       fetch_all_rows($dbh,"select min(dummy1),max(dummy1) from bench1");
  389.     }
  390.     $count++;
  391.     $sth=$dbh->prepare($query="select count(*) from bench1 where id >= " .
  392.                ($opt_loop_count*2)) or die $DBI::errstr;
  393.     $sth->execute or die $DBI::errstr;
  394.     if (($sth->fetchrow_array)[0] != $opt_loop_count)
  395.     {
  396.       print "Warning: '$query' returned wrong result\n";
  397.     }
  398.     $sth->finish;
  399.  
  400.  
  401.     $count++;
  402.     $sth=$dbh->prepare($query="select count(*),sum(id+0.0),min(id),max(id),avg(id+0.0) from bench1") or die $DBI::errstr;
  403.     $sth->execute or die $DBI::errstr;
  404.     @row=$sth->fetchrow_array;
  405.     if ($row[0] != $total_rows ||
  406.     int($row[1]+0.5) != int((($total_rows-1)/2*$total_rows)+0.5) ||
  407.     $row[2] != 0 ||
  408.     $row[3] != $total_rows-1 ||
  409.     1-$row[4]/(($total_rows-1)/2) > 0.001)
  410.     {
  411.       # PostgreSQL 6.3 fails here
  412.       print "Warning: '$query' returned wrong result: @row\n";
  413.     }
  414.     $sth->finish;
  415.  
  416.     if ($limits->{'func_odbc_mod'})
  417.     {
  418.       $tmp="mod(id,10)";
  419.       if ($limits->{'func_extra_%'})
  420.       {
  421.     $tmp="id % 10";        # For postgreSQL
  422.       }
  423.       $count++;
  424.       if ($limits->{'group_by_alias'}) {
  425.     if (fetch_all_rows($dbh,$query=$server->query("select $tmp as last_digit,count(*) from bench1 group by last_digit")) != 10)
  426.     {
  427.       print "Warning: '$query' returned wrong number of rows\n";
  428.     }
  429.       } elsif ($limits->{'group_by_position'}) {
  430.     if (fetch_all_rows($dbh,$query=$server->query("select $tmp,count(*) from bench1 group by 1")) != 10)
  431.     {
  432.       print "Warning: '$query' returned wrong number of rows\n";
  433.     }
  434.       }
  435.     }
  436.  
  437.     if ($limits->{'order_by_position'} && $limits->{'group_by_position'})
  438.     {
  439.       $count++;
  440.       if (fetch_all_rows($dbh, $query="select id,id3,dummy1 from bench1 where id < 100+$count-$count group by id,id3,dummy1 order by id desc,id3,dummy1") != 100)
  441.       {
  442.     print "Warning: '$query' returned wrong number of rows\n";
  443.       }
  444.     }
  445.   }
  446.   $end_time=new Benchmark;
  447.   print "Time for select_group ($count): " .
  448.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  449.  
  450.   $loop_time=new Benchmark;
  451.   $count=$estimated=0;
  452.   for ($tests=1 ; $tests <= $range_loop_count ; $tests++)
  453.   {
  454.     $count+=6;
  455.     fetch_all_rows($dbh,"select min(id) from bench1");
  456.     fetch_all_rows($dbh,"select max(id) from bench1");
  457.     fetch_all_rows($dbh,"select min(id2) from bench1 where id=$tests");
  458.     fetch_all_rows($dbh,"select max(id2) from bench1 where id=$tests");
  459.     if ($limits->{'group_func_sql_min_str'})
  460.     {
  461.       fetch_all_rows($dbh,"select min(dummy1) from bench1 where id=$tests");
  462.       fetch_all_rows($dbh,"select max(dummy1) from bench1 where id=$tests");
  463.     }
  464.     $end_time=new Benchmark;
  465.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
  466.                        $range_loop_count));
  467.   }
  468.   if ($estimated)
  469.   { print "Estimated time"; }
  470.   else
  471.   { print "Time"; }
  472.   print " for min_max_on_key ($count): " .
  473.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  474.  
  475.   $loop_time=new Benchmark;
  476.   $count=$estimated=0;
  477.   for ($tests=1 ; $tests <= $small_loop_count ; $tests++)
  478.   {
  479.     $count+=6;
  480.     fetch_all_rows($dbh,"select min(id2) from bench1");
  481.     fetch_all_rows($dbh,"select max(id2) from bench1");
  482.     fetch_all_rows($dbh,"select min(id3) from bench1 where id2=$tests");
  483.     fetch_all_rows($dbh,"select max(id3) from bench1 where id2=$tests");
  484.     if ($limits->{'group_func_sql_min_str'})
  485.     {
  486.       fetch_all_rows($dbh,"select min(dummy1) from bench1 where id2=$tests");
  487.       fetch_all_rows($dbh,"select max(dummy1) from bench1 where id2=$tests");
  488.     }
  489.     $end_time=new Benchmark;
  490.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
  491.                        $range_loop_count));
  492.   }
  493.   if ($estimated)
  494.   { print "Estimated time"; }
  495.   else
  496.   { print "Time"; }
  497.   print " for min_max ($count): " .
  498.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  499.  
  500.   $loop_time=new Benchmark;
  501.   $count=0;
  502.   $total=$opt_loop_count*3;
  503.   for ($tests=0 ; $tests < $total ; $tests+=$total/100)
  504.   {
  505.     $count+=1;
  506.     fetch_all_rows($dbh,"select count(id) from bench1 where id < $tests");
  507.   }
  508.   $end_time=new Benchmark;
  509.   print "Time for count_on_key ($count): " .
  510.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  511.  
  512.   $loop_time=new Benchmark;
  513.   $count=0;
  514.   for ($tests=0 ; $tests < $total ; $tests+=$total/100)
  515.   {
  516.     $count+=1;
  517.     fetch_all_rows($dbh,"select count(dummy1) from bench1 where id2 < $tests");
  518.   }
  519.   $end_time=new Benchmark;
  520.   print "Time for count ($count): " .
  521.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  522. }
  523.  
  524.  
  525. ####
  526. #### Some updates on the table
  527. ####
  528.  
  529. $loop_time=new Benchmark;
  530.  
  531. if ($limits->{'functions'})
  532. {
  533.   print "\nTesting update with functions\n";
  534.   for ($i=0 ; $i < $range_loop_count ; $i++)
  535.   {
  536.     my $tmp=$opt_loop_count+$random[$i]; # $opt_loop_count*2 <= $tmp < $total_rows
  537.     $sth = $dbh->do("update bench1 set id3=-$tmp where id3=$tmp") or die $DBI::errstr;
  538.   }
  539.  
  540.   $end_time=new Benchmark;
  541.   print "Time for update_key ($range_loop_count):  " .
  542.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  543.  
  544.   if ($opt_fast && $opt_server eq "pg")
  545.   {
  546.     $server->vacuum($dbh);
  547.   }
  548.  
  549.   ## Oracle runs out of rollback segments here if using the default "small"
  550.   ## configuration so disconnect and reconnect to use a new segment
  551.   if ( $opt_server =~ /Oracle/i ) {
  552.     $dbh->disconnect;                # close connection
  553.     $dbh = $server->connect();
  554.   }
  555.  
  556.   $loop_time=new Benchmark;
  557.   $count=0;
  558.   $step=int($opt_loop_count/$range_loop_count+1);
  559.   for ($i= 0 ; $i < $opt_loop_count ; $i+= $step)
  560.   {
  561.     $count++;
  562.     $sth=$dbh->do("update bench1 set id3= 0-id3 where id3 >= 0 and id3 <= $i") or die $DBI::errstr;
  563.   }
  564.  
  565.   $count++;
  566.   $sth=$dbh->do("update bench1 set id3= 0-id3 where id3 >= 0 and id3 < $opt_loop_count") or die $DBI::errstr;
  567.  
  568.   $count++;
  569.   $sth=$dbh->do("update bench1 set id3= 0-id3 where id3 >= $opt_loop_count and id3 < ". ($opt_loop_count*2)) or die $DBI::errstr;
  570.  
  571.   #
  572.   # Check that everything was updated
  573.   # In principle we shouldn't time this in the update loop..
  574.   #
  575.   $row_count=0;
  576.   if (($sth=$dbh->prepare("select count(*) from bench1 where id3>=0"))
  577.       && $sth->execute)
  578.   {
  579.     ($row_count)=$sth->fetchrow;
  580.   }
  581.   $result=1 + $opt_loop_count-$range_loop_count;
  582.   if ($row_count != $result)
  583.   {
  584.     print "Warning: Update check returned $row_count instead of $result\n";
  585.   }
  586.  
  587.   #restore id3 to 0 <= id3 < $total_rows
  588.   $count++;
  589.   $sth=$dbh->do($query="update bench1 set id3= 0-id3 where id3<0") or die $DBI::errstr;
  590.  
  591.   $end_time=new Benchmark;
  592.   print "Time for update_key_big ($count): " .
  593.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  594. }
  595. else
  596. {
  597.   print "\nTesting update loops\n";
  598.   #
  599.   # This is for mSQL that doesn't have functions. Do we really need this ????
  600.   #
  601.  
  602.   $sth=$dbh->prepare("select id3 from bench1 where id3 >= 0") or die $DBI::errstr;
  603.   $sth->execute or die $DBI::errstr;
  604.   $count=0;
  605.   while (@tmp = $sth->fetchrow_array)
  606.   {
  607.     my $tmp1 = "-$tmp[0]";
  608.     my $sth1 = $dbh->do("update bench1 set id3 = $tmp1 where id3 = $tmp[0]");
  609.     $count++;
  610.     $end_time=new Benchmark;
  611.     if (($end_time->[0] - $loop_time->[0]) > $opt_time_limit)
  612.     {
  613.       print "note: Aborting update loop because of timeout\n";
  614.       last;
  615.     }
  616.   }
  617.   $sth->finish;
  618.   # Check that everything except id3=0 was updated
  619.   # In principle we shouldn't time this in the update loop..
  620.   #
  621.   if (fetch_all_rows($dbh,$query="select * from bench1 where id3>=0") != 1)
  622.   {
  623.     if ($count == $total_rows)
  624.     {
  625.       print "Warning: Wrong information after update: Found '$row_count' rows, but should have been: 1\n";
  626.     }
  627.   }
  628.   #restore id3 to 0 <= id3 < $total_rows
  629.   $sth=$dbh->prepare("select id3 from bench1 where id3 < 0") or die $DBI::errstr;
  630.   $sth->execute or die $DBI::errstr;
  631.   while (@tmp = $sth->fetchrow_array)
  632.   {
  633.     $count++;
  634.     $tmp1 = 0-$tmp[0];
  635.     $sth1 = $dbh->do("update bench1 set id3 = $tmp1 where id3 = $tmp[0]");
  636.   }
  637.   $sth->finish;
  638.   $end_time=new Benchmark;
  639.   $estimated=predict_query_time($loop_time,$end_time,\$count,$count,
  640.                 $opt_loop_count*6);
  641.   if ($estimated)
  642.   { print "Estimated time"; }
  643.   else
  644.   { print "Time"; }
  645.   print " for update_key ($count): " .
  646.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  647. }
  648.  
  649. if ($opt_fast && $opt_server eq "pg")
  650. {
  651.   $server->vacuum($dbh);
  652. }
  653.  
  654. ## Oracle runs out of rollback segments here if using the default "small" configuration
  655. ## so disconnect and reconnect to use a new segment
  656. if ( $opt_server =~ /Oracle/i ) {
  657.   $dbh->disconnect;                # close connection
  658.   $dbh = $server->connect();
  659. }
  660.  
  661. ####
  662. #### Do some deletes on the table
  663. ####
  664.  
  665. if (!$opt_skip_delete)
  666. {
  667.   print "Testing delete\n";
  668.   $loop_time=new Benchmark;
  669.   $count=0;
  670.   for ($i=0 ; $i < $opt_loop_count ; $i+=$opt_loop_count/$range_loop_count)
  671.   {
  672.     $count++;
  673.     $tmp=$opt_loop_count+$random[$i]; # $opt_loop_count*2 <= $tmp < $total_rows
  674.     $dbh->do("delete from bench1 where id3=$tmp") or die $DBI::errstr;
  675.   }
  676.  
  677.   $end_time=new Benchmark;
  678.   print "Time for delete_key ($count): " .
  679.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  680.  
  681.   if ($opt_fast && $opt_server eq "pg")
  682.   {
  683.     $server->vacuum($dbh);
  684.   }
  685.  
  686.   $count=0;
  687.   $loop_time=new Benchmark;
  688.   for ($i= 0 ; $i < $opt_loop_count ; $i+=$opt_loop_count/10)
  689.   {
  690.     $sth=$dbh->do("delete from bench1 where id3 >= 0 and id3 <= $i") or die $DBI::errstr;
  691.     $count++;
  692.   }
  693.   $count+=2;
  694.   $sth=$dbh->do("delete from bench1 where id3 >= 0 and id3 <= $opt_loop_count") or die $DBI::errstr;
  695.  
  696.   $sth=$dbh->do("delete from bench1 where id >= $opt_loop_count and id <= " . ($opt_loop_count*2) ) or die $DBI::errstr;
  697.  
  698.   if ($opt_fast)
  699.   {
  700.     $sth=$dbh->do("delete from bench1") or die $DBI::errstr;
  701.   }
  702.   else
  703.   {
  704.     $sth = $dbh->do("delete from bench1 where id3 < " . ($total_rows)) or die $DBI::errstr;
  705.   }
  706.  
  707.   $end_time=new Benchmark;
  708.   print "Time for delete_big ($count): " .
  709.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  710.  
  711.   if ($opt_lock_tables)
  712.   {
  713.     $sth = $dbh->do("UNLOCK TABLES ") || die $DBI::errstr;
  714.   }
  715.   $sth = $dbh->do("drop table bench1") or die $DBI::errstr;
  716. }
  717.  
  718. if ($opt_fast && $opt_server eq "pg")
  719. {
  720.   $server->vacuum($dbh);
  721. }
  722.  
  723.  
  724. keys_test:
  725. #
  726. # Test of insert in table with many keys
  727. # This test assumes that the server really create the keys!
  728. #
  729.  
  730. my @fields=(); my @keys=();
  731. $keys=min($limits->{'max_index'},16);          # 16 is more than enough
  732. $seg= min($limits->{'max_index_parts'},$keys,16); # 16 is more than enough
  733.  
  734. print "Insert into table with $keys keys and with a primary key with $seg parts\n";
  735.  
  736. # Make keys on the most important types
  737. @types=(0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,1,1);    # A 1 for each char field
  738. push(@fields,"field1 tinyint not null");
  739. push(@fields,"field2 mediumint not null");
  740. push(@fields,"field3 smallint not null");
  741. push(@fields,"field4 char(16) not null");
  742. push(@fields,"field5 integer not null");
  743. push(@fields,"field6 float not null");
  744. push(@fields,"field7 double not null");
  745. for ($i=8 ; $i <= $keys ; $i++)
  746. {
  747.   push(@fields,"field$i char(6) not null");    # Should be relatively fair
  748. }
  749.  
  750. # First key contains many segments
  751. $query="primary key (";
  752. for ($i= 1 ; $i <= $seg ; $i++)
  753. {
  754.   $query.= "field$i,";
  755. }
  756. substr($query,-1)=")";
  757. push (@keys,$query);
  758.  
  759. #Create other keys
  760. for ($i=2 ; $i <= $keys ; $i++)
  761. {
  762.   push(@keys,"index index$i (field$i)");
  763. }
  764.  
  765. do_many($dbh,$server->create("bench1",\@fields,\@keys));
  766. if ($opt_lock_tables)
  767. {
  768.   $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  769. }
  770.  
  771. if ($opt_fast && $opt_server eq "pg")
  772. {
  773.   $server->vacuum($dbh);
  774. }
  775.  
  776. $loop_time=new Benchmark;
  777. $fields=$#fields;
  778. if (($opt_fast || $opt_fast_insert) && $limits->{'multi_value_insert'})
  779. {
  780.   $query_size=$server->{'limits'}->{'query_size'};
  781.   $query="insert into bench1 values ";
  782.   $res=$query;
  783.   for ($i=0; $i < $many_keys_loop_count; $i++)
  784.   {
  785.     $rand=$random[$i];
  786.     $tmp="(" . ($i & 127) . ",$rand," . ($i & 32766) .
  787.       ",'ABCDEF$rand',0,";
  788.  
  789.     for ($j=5; $j <= $fields ; $j++)
  790.     {
  791.       $tmp.= ($types[$j] == 0) ? "$rand," : "'$rand',";
  792.     }
  793.     substr($tmp,-1)=")";
  794.     if (length($tmp)+length($res) < $query_size)
  795.     {
  796.       $res.= $tmp . ",";
  797.     }
  798.     else
  799.     {
  800.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  801.       $res=$query . $tmp . ",";
  802.     }
  803.   }
  804.   $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  805. }
  806. else
  807. {
  808.   for ($i=0; $i < $many_keys_loop_count; $i++)
  809.   {
  810.     $rand=$random[$i];
  811.     $query="insert into bench1 values (" . ($i & 127) . ",$rand," . ($i & 32767) .
  812.       ",'ABCDEF$rand',0,";
  813.  
  814.     for ($j=5; $j <= $fields ; $j++)
  815.     {
  816.       $query.= ($types[$j] == 0) ? "$rand," : "'$rand',";
  817.     }
  818.     substr($query,-1)=")";
  819.     print "query1: $query\n" if ($opt_debug);
  820.     $dbh->do($query) or die "Got error $DBI::errstr with query: $query\n";
  821.   }
  822. }
  823. $end_time=new Benchmark;
  824. print "Time for insert_key ($many_keys_loop_count): " .
  825.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  826.  
  827. if ($opt_fast && $opt_server eq "pg")
  828. {
  829.   $server->vacuum($dbh);
  830. }
  831.  
  832. #
  833. # update one key of the above
  834. #
  835.  
  836. print "Testing update of keys\n";
  837. $loop_time=new Benchmark;
  838. for ($i=0 ; $i< 256; $i++)
  839. {
  840.   $dbh->do("update bench1 set field5=1 where field1=$i")
  841.     or die "Got error $DBI::errstr with query: update bench1 set field5=1 where field1=$i\n";
  842. }
  843. $end_time=new Benchmark;
  844. print "Time for update_of_key (256): " .
  845.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  846.  
  847. if ($opt_fast && $opt_server eq "pg")
  848. {
  849.   $server->vacuum($dbh);
  850. }
  851.  
  852. ## Oracle runs out of rollback segments here if using the default "small" configuration
  853. ## so disconnect and reconnect to use a new segment
  854. if ( $opt_server =~ /Oracle/i || $opt_server =~ /db2/i)
  855. {
  856.   $dbh->disconnect;                # close connection
  857.   $dbh = $server->connect();
  858. }
  859.  
  860. #
  861. # Delete everything from table
  862. #
  863.  
  864. print "Deleting everything from table\n";
  865. $loop_time=new Benchmark;
  866. $count=0;
  867. if ($opt_fast)
  868. {
  869.   $dbh->do("delete from bench1 where field1 = 0") or die $DBI::errstr;
  870.   $dbh->do("delete from bench1") or die $DBI::errstr;
  871.   $count+=2;
  872. }
  873. else
  874. {
  875.   $dbh->do("delete from bench1 where field1 = 0") or die $DBI::errstr;
  876.   $dbh->do("delete from bench1 where field1 > 0") or die $DBI::errstr;
  877.   $count+=2;
  878. }
  879.  
  880. if ($opt_lock_tables)
  881. {
  882.   $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
  883. }
  884.  
  885. $end_time=new Benchmark;
  886. print "Time for delete_big ($count): " .
  887.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  888.  
  889. $sth = $dbh->do("drop table bench1") or die $DBI::errstr;
  890. if ($opt_fast && $opt_server eq "pg")
  891. {
  892.   $server->vacuum($dbh);
  893. }
  894.  
  895. #
  896. # Test multi value inserts if the server supports it
  897. #
  898.  
  899. if ($limits->{'multi_value_insert'})
  900. {
  901.   $query_size=$limits->{'query_size'}; # Same limit for all databases
  902.  
  903.   $sth = $dbh->do("drop table bench1");
  904.   do_many($dbh,$server->create("bench1",
  905.                    ["id int NOT NULL",
  906.                 "id2 int NOT NULL",
  907.                 "id3 int NOT NULL",
  908.                 "dummy1 char(30)"],
  909.                    ["primary key (id,id2)",
  910.                    "index index_id3 (id3)"]));
  911.   if ($opt_lock_tables)
  912.   {
  913.     $sth = $dbh->do("LOCK TABLES bench1 write") || die $DBI::errstr;
  914.   }
  915.  
  916.   $loop_time=new Benchmark;
  917.   print "Inserting $opt_loop_count rows with multiple values\n";
  918.   $query="insert into bench1 values ";
  919.   $res=$query;
  920.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  921.   {
  922.     my $tmp= "($i,$i,$i,'EFGHIJKLM'),";
  923.     if (length($i)+length($res) < $query_size)
  924.     {
  925.       $res.= $tmp;
  926.     }
  927.     else
  928.     {
  929.       do_query($dbh,substr($res,0,length($res)-1));
  930.       $res=$query .$tmp;
  931.     }
  932.   }
  933.   do_query($dbh,substr($res,0,length($res)-1));
  934.  
  935.   $end_time=new Benchmark;
  936.   print "Time for multiple_value_insert (" . ($opt_loop_count) . "): " .
  937.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  938.  
  939.   if ($opt_fast && $opt_server eq "pg")
  940.   {
  941.     $server->vacuum($dbh);
  942.   }
  943.   if ($opt_lock_tables)
  944.   {
  945.     $sth = $dbh->do("UNLOCK TABLES ") || die $DBI::errstr;
  946.   }
  947.  
  948.   # A big table may take a while to drop
  949.   $loop_time=new Benchmark;
  950.   $sth = $dbh->do("drop table bench1") or die $DBI::errstr;
  951.   $end_time=new Benchmark;
  952.   print "Time for drop table(1): " .
  953.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  954. }
  955.  
  956. ####
  957. #### End of benchmark
  958. ####
  959.  
  960. $dbh->disconnect;                # close connection
  961.  
  962. end_benchmark($start_time);
  963.  
  964. ###
  965. ### Some help functions
  966. ###
  967.  
  968.  
  969. # Do some sample selects on direct key
  970. # First select finds a row, the second one doesn't find.
  971.  
  972. sub check_select_key
  973. {
  974.   my ($column,$check)= @_;
  975.   my ($loop_time,$end_time,$i,$tmp_var,$tmp,$count,$row_count,$estimated);
  976.  
  977.   $estimated=0;
  978.   $loop_time=new Benchmark;
  979.   $count=0;
  980.   for ($i=1 ; $i <= $opt_loop_count; $i++)
  981.   {
  982.     $count+=2;
  983.     $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  984.     $tmp=$tmpvar % ($total_rows);
  985.     fetch_all_rows($dbh,"select * from bench1 where $column=$tmp")
  986.       or die $DBI::errstr;
  987.     $tmp+=$total_rows;
  988.     defined($row_count=fetch_all_rows($dbh,"select * from bench1 where $column=$tmp")) or die $DBI::errstr;
  989.     die "Found $row_count rows on impossible id: $tmp\n" if ($row_count);
  990.     $end_time=new Benchmark;
  991.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i,
  992.                        $opt_loop_count));
  993.   }
  994.   if ($estimated)
  995.   { print "Estimated time"; }
  996.   else
  997.   { print "Time"; }
  998.   print " for $check ($count): " .
  999.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1000. }
  1001.  
  1002. #
  1003. # Search using some very simple queries
  1004. #
  1005.  
  1006. sub check_select_range
  1007. {
  1008.   my ($column,$check)= @_;
  1009.   my ($loop_time,$end_time,$i,$tmp_var,$tmp,$query,$rows,$estimated);
  1010.  
  1011.   $estimated=0;
  1012.   $loop_time=new Benchmark;
  1013.   $found=$count=0;
  1014.   for ($test=1 ; $test <= $range_loop_count; $test++)
  1015.   {
  1016.     $count+=$#Q+1;
  1017.     for ($i=0 ; $i < $#Q ; $i+=2)
  1018.     {
  1019.       $query=$Q[$i];
  1020.       $rows=$Q[$i+1];
  1021.       $query =~ s/!id!/$column/g;
  1022.       if (($row_count=fetch_all_rows($dbh,$query)) != $rows)
  1023.       {
  1024.     if ($row_count == undef())
  1025.     {
  1026.       die "Got error: $DBI::errstr when executing $query\n";
  1027.     }
  1028.     die "'$query' returned wrong number of rows: $row_count instead of $rows\n";
  1029.       }
  1030.       $found+=$row_count;
  1031.     }
  1032.     $end_time=new Benchmark;
  1033.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$test,
  1034.                        $range_loop_count));
  1035.   }
  1036.   if ($estimated)
  1037.   { print "Estimated time"; }
  1038.   else
  1039.   { print "Time"; }
  1040.   $end_time=new Benchmark;
  1041.   print " for $check ($count:$found): " .
  1042.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1043. }
  1044.  
  1045.  
  1046. #
  1047. # SELECT * from bench where col=x or col=x or col=x ...
  1048.  
  1049.  
  1050. sub check_or_range
  1051. {
  1052.   my ($column,$check)= @_;
  1053.   my ($loop_time,$end_time,$i,$tmp_var,$tmp,$columns,$estimated,$found,
  1054.       $or_part,$count,$loop_count);
  1055.  
  1056.   $columns=min($limits->{'max_columns'},50,($limits->{'query_size'}-50)/13);
  1057.   $columns=$columns- ($columns % 4); # Make Divisible by 4
  1058.  
  1059.   $estimated=0;
  1060.   $loop_time=new Benchmark;
  1061.   $found=0;
  1062.   $loop_count=$range_loop_count*10;
  1063.   for ($count=0 ; $count < $loop_count ; )
  1064.   {
  1065.     for ($rowcnt=0; $rowcnt <= $columns; $rowcnt+= $columns/4)
  1066.     {
  1067.       my $query="select * from bench1 where ";
  1068.       my $or_part= "$column = 1";
  1069.       $count+=2;
  1070.  
  1071.       for ($i=1 ; $i < $rowcnt ; $i++)
  1072.       {
  1073.     $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  1074.     $tmp=$tmpvar % ($opt_loop_count*4);
  1075.     $or_part.=" or $column=$tmp";
  1076.       }
  1077.       print $query . $or_part . "\n" if ($opt_debug);
  1078.       ($rows=fetch_all_rows($dbh,$query . $or_part)) or die $DBI::errstr;
  1079.       $found+=$rows;
  1080.  
  1081.       if ($limits->{'func_extra_in_num'})
  1082.       {
  1083.     my $in_part=$or_part;    # Same query, but use 'func_extra_in_num' instead.
  1084.     $in_part=~ s/ = / IN \(/;
  1085.     $in_part=~ s/ or $column=/,/g;
  1086.     $in_part.= ")";
  1087.     fetch_all_rows($dbh,$query . $in_part) or die $DBI::errstr;
  1088.     $count++;
  1089.       }
  1090.       # Do it a little harder by setting a extra range
  1091.       defined(($rows=fetch_all_rows($dbh,"$query($or_part) and $column < 10"))) or die $DBI::errstr;
  1092.       $found+=$rows;
  1093.     }
  1094.     $end_time=new Benchmark;
  1095.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
  1096.                        $loop_count));
  1097.   }
  1098.  
  1099.   if ($estimated)
  1100.   { print "Estimated time"; }
  1101.   else
  1102.   { print "Time"; }
  1103.   print " for $check ($count:$found): " .
  1104.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1105. }
  1106.